#ifndef XPM_EDITOR_PANEL_H
#define XPM_EDITOR_PANEL_H

class wxDragImage;

#include <wx/image.h>
#include <wx/bitmap.h>
#include <wx/generic/dragimgg.h>
#include <wx/panel.h>
class wxSpinEvent;
class wxCheckBox;
class wxTextCtrl;
class XPMColorPicker;
class wxComboBox;
class wxCustomButton;
class wxScrolledWindow;
class wxStaticText;
class wxToggleButton;
class wxSpinCtrl;
class wxBoxSizer;
class wxResizeCtrl;
class wxButton;

#define XPM_NUMBER_TOOLS 14
#define XPM_MAXPOINTS 25

enum {
  XPM_CIRCLE_INDEX = 0,
  XPM_SQUARE_INDEX = 1,
  XPM_LEFT_HAIR_INDEX = 2,
  XPM_RIGHT_HAIR_INDEX = 3
};

enum {
  XPM_CIRCLE_INDEX_LIST = 0,
  XPM_SQUARE_INDEX_LIST = 1,
  XPM_LEFT_HAIR_INDEX_LIST = 2,
  XPM_RIGHT_HAIR_INDEX_LIST = 3
};

enum {
  XPM_ID_SELECT_TOOL = 0,
  XPM_ID_LASSO_TOOL,
  XPM_ID_PEN_TOOL,
  XPM_ID_BRUSH_TOOL,
  XPM_ID_PIPETTE_TOOL,
  XPM_ID_FILL_TOOL,
  XPM_ID_CURVE_TOOL,
  XPM_ID_LINE_TOOL,
  XPM_ID_ERASER_TOOL,
  XPM_ID_TEXT_TOOL,
  XPM_ID_RECTANGLE_TOOL,
  XPM_ID_POLYGON_TOOL,
  XPM_ID_ELLIPSE_TOOL,
  XPM_ID_ROUNDEDRECT_TOOL
};

struct ToolData {
  int x1;
  int y1;
  int x2;
  int y2;
  int iNbClicks;
  int iStyle;
  int iSize;
  wxPoint pts[XPM_MAXPOINTS + 1];
  int iNbPoints;
  int iRadius;
  wxString sText;
  wxFont font;
  int iHorizAlign;
  int iVertAlign;
  double angle;
};

class XPMUndo;

class XPMEditorPanel: public wxPanel {
  public:

    XPMEditorPanel( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize );
    virtual ~XPMEditorPanel();

    //Bitmap & draw canvas access
    wxImage GetImage( void );
    void SetImage( wxImage *img );
    wxScrolledWindow* GetDrawCanvas( void );

    void SetModified( bool bModified );
    bool GetModified( void );

    //sizing & scaling
    double GetScaleFactor( void );
    void SetScaleFactor( double dNewScalingFactor );
    wxSize GetDrawAreaSize( void );
    void SetDrawAreaSize( wxSize sNewDrawAreaSize );

    //Selection methods
    bool HasSelection( void ) const;
    void ClearSelection( void );
    void GetBoundingRect( wxRect *r );
    int IsPointInSelection( int x, int y );
    void ReplaceRect( const wxImage &newImage, wxRect rRect );
    void PasteImage( const wxImage &newImage, int x, int y );
    void ConvertSelectionToRect( void );

    //UNDO & REDO Methods
    bool CanUndo( void ) const;
    bool CanRedo( void ) const;
    void ClearUndoBuffer( void );
    void ClearRedoBuffer( void );
    bool AddUndo( wxBitmap *bm );
    bool AddRedo( wxBitmap *bm );
    bool AddUndo( wxImage *img );
    bool AddRedo( wxImage *img );
    bool AddUndo( void );
    bool AddRedo( void );
    void Undo( void );
    void Redo( void );
    void Cut( void );
    void Copy( void );
    void Paste( void );
    void UpdateConfiguration( void );

    wxBoxSizer* ToolSizer;
    wxCustomButton* FillButton;
    wxCustomButton* EraserButton;
    wxSpinCtrl* BMPHeight;
    wxStaticText* sCursorPos;
    wxScrolledWindow* DrawCanvas;
    wxSpinCtrl* SpinCtrl1;
    wxSpinCtrl* BMPWidth;
    wxStaticText* StaticText2;
    wxBoxSizer* CanvasSizer;
    wxTextCtrl* TextEdit;
    wxCustomButton* SquareBrushButton;
    wxStaticText* StaticText6;
    wxCustomButton* BrushButton;
    wxCustomButton* LineButton;
    wxCustomButton* PenButton;
    wxStaticText* StaticText1;
    wxStaticText* StaticText3;
    wxPanel* ToolPanel;
    wxCheckBox* CheckBox1;
    wxButton* FontButton;
    wxCustomButton* PipetteButton;
    wxSpinCtrl* SpinCtrl3;
    wxStaticText* StaticText5;
    wxCustomButton* SelectButton;
    wxResizeCtrl* ResizeCtrl1;
    wxCustomButton* EllipseButton;
    wxCustomButton* RHairBrushButton;
    wxSpinCtrl* SpinCtrl2;
    wxComboBox* ZoomFactor;
    XPMColorPicker* ColourPicker;
    wxBoxSizer* PanelSizer;
    wxToggleButton* BackgroundButton;
    wxCustomButton* LassoButton;
    wxCustomButton* RectangleButton;
    wxCustomButton* CircleBrushButton;
    wxCustomButton* RRectButton;
    wxBoxSizer* ToolPanelSizer;
    wxStaticText* StaticText4;
    wxCustomButton* LHairBrushButton;
    wxCustomButton* CurveButton;
    wxCustomButton* TextButton;
    wxCustomButton* PolygonButton;
  protected:
    static const long ID_STATICTEXT1;
    static const long ID_COMBOBOX1;
    static const long ID_STATICTEXT2;
    static const long ID_SPINCTRL1;
    static const long ID_STATICTEXT3;
    static const long ID_SPINCTRL2;
    static const long ID_CHECKBOX1;
    static const long ID_CUSTOM1;
    static const long ID_SELECT_BUTN;
    static const long ID_LASSO_BTN;
    static const long ID_PEN_BTN;
    static const long ID_BRUSH_BTN;
    static const long ID_PIPETTE_BTN;
    static const long ID_FILL_BTN;
    static const long ID_LINE_BTN;
    static const long ID_CURVE_BTN;
    static const long ID_ERASER_BTN;
    static const long ID_TEXT_BTN;
    static const long ID_RECTANGLE_BTN;
    static const long ID_POLYGON_BTN;
    static const long ID_ELLIPSE_BTN;
    static const long ID_ROUNDEDRECT_BTN;
    static const long ID_SQUARE_BRUSH;
    static const long ID_CIRCLE_BRUSH;
    static const long ID_LRHAIR_BRUSH;
    static const long ID_LHAIR_BRUSH;
    static const long ID_FONT_BUTTON;
    static const long ID_BKMODE_TOGGLEBUTTON;
    static const long ID_STATICTEXT5;
    static const long ID_SPINCTRL3;
    static const long ID_STATICTEXT7;
    static const long ID_SPINCTRL5;
    static const long ID_STATICTEXT6;
    static const long ID_SPINCTRL4;
    static const long ID_PANEL1;
    static const long ID_TEXTCTRL1;
    static const long ID_RESIZECTRL1;
    static const long ID_SCROLLEDWINDOW1;
    static const long ID_STATICTEXT4;
    void OnDrawCanvasPaint( wxPaintEvent& event );
    void OnBitmapSizeChanged( wxSpinEvent& event );
    void OnZoomChanged( wxCommandEvent& event );
    void OnDrawCanvasResize( wxSizeEvent& event );
    void OnShowGrid( wxCommandEvent& event );
    void OnDrawCanvasMouseMove( wxMouseEvent& event );
    void OnDrawCanvasLeftDown( wxMouseEvent& event );
    void OnDrawCanvasLeftUp( wxMouseEvent& event );
    void OnDrawCanvasMouseLeave( wxMouseEvent& event );
    void OnDrawCanvasLeftDClick( wxMouseEvent& event );
    void OnDrawCanvasEraseBackground( wxEraseEvent& event );
    void OnSpinSizeChanged( wxSpinEvent& event );
    void OnSpinRadiusChanged( wxSpinEvent& event );
    void OnEllipseButtonToggle( wxCommandEvent& event );
    void OnRRectButtonToggle( wxCommandEvent& event );
    void OnRectangleButtonToggle( wxCommandEvent& event );
    void OnPolygonButtonToggle( wxCommandEvent& event );
    void OnEraserButtonToggle( wxCommandEvent& event );
    void OnTextButtonToggle( wxCommandEvent& event );
    void OnCurveButtonToggle( wxCommandEvent& event );
    void OnLineButtonToggle( wxCommandEvent& event );
    void OnPipetteButtonToggle( wxCommandEvent& event );
    void OnFillButtonToggle( wxCommandEvent& event );
    void OnPenButtonToggle( wxCommandEvent& event );
    void OnBrushButtonToggle( wxCommandEvent& event );
    void OnLassoButtonToggle( wxCommandEvent& event );
    void OnSelectButtonToggle( wxCommandEvent& event );
    void OnSquareBrushButtonToggle( wxCommandEvent& event );
    void OnCircleBrushButtonToggle( wxCommandEvent& event );
    void OnLHairBrushButtonToggle( wxCommandEvent& event );
    void OnRHairBrushButtonToggle( wxCommandEvent& event );
    void OnDrawCanvasRightUp( wxMouseEvent& event );
    void OnFontButtonClick( wxCommandEvent& event );
    void OnBackgroundButtonToggle( wxCommandEvent& event );
    void OnTextEditText( wxCommandEvent& event );
    void OnDrawCanvasKeyDown( wxKeyEvent& event );

    void OnTransparentColorChanged( wxCommandEvent& event );
    void OnLineColorChanged( wxCommandEvent& event );
    void OnFillColorChanged( wxCommandEvent& event );

    void BuildContent( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size );
    void ToggleButtons( int iIndex, bool bClearSelection = true );
    void SetToolCursor( void );
    int GetToolID( void );
    void SetToolID( int iTool );
    void ProcessToolAction( int iTool, int x, int y,
                            bool bLeftDown, bool bLeftUp,
                            bool bPressed, bool bDClick );
    void HideControls( int iIndex, bool bChecked );
    void HideControlsAndDoLayout( int iIndex, bool bChecked );
    void ProcessPen( int x, int y,
                     bool bLeftDown, bool bLeftUp,
                     bool bPressed, bool bDClick );
    void ProcessFill( int x, int y,
                      bool bLeftDown, bool bLeftUp,
                      bool bPressed, bool bDClick );
    void ProcessPipette( int x, int y,
                         bool bLeftDown, bool bLeftUp,
                         bool bPressed, bool bDClick );
    void ProcessSelect( int x, int y,
                        bool bLeftDown, bool bLeftUp,
                        bool bPressed, bool bDClick );
    void ProcessLasso( int x, int y,
                       bool bLeftDown, bool bLeftUp,
                       bool bPressed, bool bDClick );
    void ProcessRectangle( int x, int y,
                           bool bLeftDown, bool bLeftUp,
                           bool bPressed, bool bDClick );
    void ProcessLine( int x, int y,
                      bool bLeftDown, bool bLeftUp,
                      bool bPressed, bool bDClick );
    void ProcessCurve( int x, int y,
                       bool bLeftDown, bool bLeftUp,
                       bool bPressed, bool bDClick );
    void ProcessRoundedRectangle( int x, int y,
                                  bool bLeftDown, bool bLeftUp,
                                  bool bPressed, bool bDClick );
    void ProcessEllipse( int x, int y,
                         bool bLeftDown, bool bLeftUp,
                         bool bPressed, bool bDClick );
    void ProcessPolygon( int x, int y,
                         bool bLeftDown, bool bLeftUp,
                         bool bPressed, bool bDClick );
    void ProcessEraser( int x, int y,
                        bool bLeftDown, bool bLeftUp,
                        bool bPressed, bool bDClick );
    void ProcessBrush( int x, int y,
                       bool bLeftDown, bool bLeftUp,
                       bool bPressed, bool bDClick );
    void ProcessText( int x, int y,
                      bool bLeftDown, bool bLeftUp,
                      bool bPressed, bool bDClick );
    void ProcessDragAction( int x, int y,
                            bool bLeftDown, bool bLeftUp,
                            bool bPressed, bool bDClick );
    void ProcessSizeAction( int x, int y,
                            bool bLeftDown, bool bLeftUp,
                            bool bPressed, bool bDClick, int iDirection );

  private:
    //bitmap, images methods
    wxColour cMaskColour;
    wxBitmap *m_Bitmap;
    wxImage *m_Image;
    void UpdateBitmap( void );
    void UpdateImage( void );
    wxBitmap* GetBitmap( void );
    void SetBitmap( wxBitmap *bm );

    //drag related methods & members
    wxGenericDragImage *m_DragImage;
    bool m_bDragging;
    wxImage m_SelectionImage;
    wxBitmap m_SelectionBitmap;
    bool m_bEraseSelection;
    wxPoint pStartDragging;

    //scale factor & scrollbars
    double dScale;
    bool bShowGrid;
    void DoSetScrollBars( void );

    //Sizing
    wxSize sDrawAreaSize;
    bool bCanResizeX;
    bool bCanResizeY;
    bool bSizingX;
    bool bSizingY;
    int OldX;
    int OldY;

    //Text tool methods & members
    void DrawTextRectangle( wxDC& dc,
                            const wxString& value,
                            const wxRect& rect,
                            int horizAlign,
                            int vertAlign,
                            double textOrientation );
    void DrawTextRectangle( wxDC& dc,
                            const wxArrayString& lines,
                            const wxRect& rect,
                            int horizAlign,
                            int vertAlign,
                            double textOrientation );
    void StringToLines( const wxString& value, wxArrayString& lines );
    void GetTextBoxSize( const wxDC& dc,
                         const wxArrayString& lines,
                         long *width, long *height );

    //Selection members & methods
    wxPoint *pSelection;
    int NbPoints;
    int NbPointsMax;
    wxPoint* CheckMemorySelection( int iNeeded );
    bool bDrawSelection;
    wxImage GetImageFromSelection( void );
    void CutSelection( void );
    void MoveSelection( int dx, int dy );
    void PasteSelection( void );
    void DrawTextBitmap( void );

    //Undo & Redo buffers
    XPMUndo *m_undo_buffer;

    //Drawing tools ids, & cursors
    wxCustomButton* tools[XPM_NUMBER_TOOLS];
    int iToolUsed;
    wxCursor ToolCursor[XPM_NUMBER_TOOLS];
    ToolData tdata;
    void InitToolData( void );
    bool bUsingTool;

    //standard configuration
    int iXPMDefaultWidth;
    int iXPMDefaultHeight;
    wxColour cBackgroundColour;


    DECLARE_EVENT_TABLE()
};

//brush style
enum {
  XPM_BRUSH_STYLE_SQUARE = 0,
  XPM_BRUSH_STYLE_CIRCLE = 1,
  XPM_BRUSH_STYLE_LEFTHAIR = 2,
  XPM_BRUSH_STYLE_RIGHTHAIR = 3
};

#endif
